#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/device.h>

#include "chip_demo_gpio_led.h"
#include "led_drv.h"


static int major;
static struct class *led_class;
struct led_chip_operations *led_chip_ops;


static int led_open (struct inode *node, struct file *filp)
{
	/* 
		打开设备时要获取其 次设备号
		通过次设备号初始化GPIO
	*/
	int minor = iminor(node);
	
	led_chip_ops->led_init(minor);

	return 0;
}


static ssize_t led_read (struct file *filp, char __user *buf, size_t size, loff_t *offset)
{
	printk("led_read\n");
	return 0;
}


static ssize_t led_write (struct file *filp, const char __user *buf, size_t size, loff_t *offset)
{
	/* 根据次设备号和 status 控制 led */
	struct inode *inode = file_inode(filp);
	int minor = iminor(inode);
	char status, err;
	
	err = copy_from_user(&status, buf, 1);
	led_chip_ops->led_ctl(minor, status);
	return 0;
}


static int led_release (struct inode *node , struct file *filp)
{
	int minor = iminor(node);
	printk("/dev/led%d close\n", minor);

	return 0;
}


static struct file_operations led_ops = {
	.owner		= THIS_MODULE,
	.open 		= led_open,
	.read 		= led_read,
	.write 		= led_write,
	.release    = led_release,
};


/*为硬件操作层提供注册设备节点函数*/
void led_device_create(int minor)
{
	device_create(led_class, NULL, MKDEV(major, minor), NULL, "led%d", minor);   // /dev/led
}

/*为硬件操作层提供销毁设备节点函数*/
void led_device_destroy(int minor)
{
	device_destroy(led_class, MKDEV(major, minor));
}

/*获取硬件操作层的 led_chip_operations 结构体*/
void get_led_resources(struct led_chip_operations *ops)
{
	led_chip_ops = ops;
}	

EXPORT_SYMBOL(led_device_create);
EXPORT_SYMBOL(led_device_destroy);
EXPORT_SYMBOL(get_led_resources);


/*led驱动入口函数：insmod时会被调用*/
static int led_drv_init(void)
{
	/* 1.注册设备 */
	major = register_chrdev(0, "led_board_drv", &led_ops);

	/* 2.自动创建设备节点 */
	/* 2.1 在内核中创建设备 */
	led_class = class_create(THIS_MODULE, "led_class");

	
	/* 2.2 创建设备节点 */
	/*
		获取led_chip_ops结构体：
		定义了led个数、led初始化函数、led控制函数
	*/
//	led_chip_ops = get_led_chip_ops();
	/* 指定次设备号创建/dev设备 */
//	device_create(led_class, NULL, MKDEV(major, 0), NULL, "led");   // /dev/led

	printk("led driver insmod success\n");
	return 0;
}


/*led驱动出口函数：rmmod时会被调用*/
static void led_drv_exit(void)
{
	/* 1.销毁设备节点 */
//	device_destroy(led_class, MKDEV(major, 0));

	/* 2.销毁设备类 */
	class_destroy(led_class);

	/* 3.卸载设备 */
	unregister_chrdev(major, "led_board_drv");

	printk("led driver exit\n");
}

module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");





